﻿/*	@file	r_math_matrix33.h
	@brief	行列
Copyright (c) 2009 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_MATH_MATRIX33_H_
#define _R_MATH_MATRIX33_H_


#include "r_math_def.h"

namespace r{
	namespace math{
		struct Vector2D;
		struct Vector3D;

		struct Matrix33 {
		public:
			//! コンストラクタ
			Matrix33();
			//! 各要素指定
			Matrix33 (
				r_f32 s11, r_f32 s12, r_f32 s13,
				r_f32 s21, r_f32 s22, r_f32 s23,
				r_f32 s31, r_f32 s32, r_f32 s33 );
			//! float[16]の配列で指定
			Matrix33 ( const r_f32 *sv );
			//! 引数valで全要素を初期化
			Matrix33 ( r_f32 val );
			//! 単位行列の作成
			void	identity ( void );

			//! 行列 X 行列
			Matrix33 operator * ( const Matrix33 &src ) const;
			///
			const Matrix33&	operator *= ( const Matrix33 &src );
			//! 全要素に引数srcを掛け合わせる
			Matrix33 operator * ( r_f32 src ) const;
			///
			const Matrix33&	operator *= ( r_f32 src );
			//! 行列の各要素同士を足し合わせる
			Matrix33 operator + ( const Matrix33 &src ) const;
			///
			const Matrix33&	operator += ( const Matrix33 &src );
			//! 行列の転置
			void	transpose ( void );

			//! スケール行列を設定
			/*!
			@param	src	[in]	x.y.zに対応したスケール成分
			*/
			const Matrix33&	scale ( const r::math::Vector3D &src );
			//! スケール行列を設定
			const Matrix33&	scale ( r_f32 src );
			//! X軸回転の行列を設定
			/*!
			@param	src	[in]	x軸での回転(ラジアン)
			*/
			const Matrix33&	rotateX ( r_f32 src );
			//! Y軸回転の行列を設定
			/*!
			@param	src	[in]	y軸での回転(ラジアン)
			*/
			const Matrix33&	rotateY ( r_f32 src );
			//! Z軸回転の行列を設定
			/*!
			@param	src	[in]	z軸での回転(ラジアン)
			*/
			const Matrix33&	rotateZ ( r_f32 src );
			//! 任意軸での回転行列を設定
			/*!
			@param	vec	[in]	回転軸
			@param	rot	[in]	回転量(ラジアン)
			*/
			const Matrix33&	rotateAxis ( const r::math::Vector3D &vec, r_f32 rot );
			//! 2次元ベクトルを(z成分を0として)現在の行列で掛け合わせて変形する
			r::math::Vector3D	transform3D ( const r::math::Vector2D &vec ) const;
			//! 3次元ベクトルを現在の行列で変形する
			r::math::Vector3D	transform3D ( const r::math::Vector3D &vec ) const;
			//! 行列の各回転成分のスケールを1.0に正規化する
			const Matrix33&	normalize ( void );
			//! 行列のスケールを取得
			/*!
			@retval	各回転成分のスケール値
			*/
			r::math::Vector3D getSize ( void ) const;
			//! 構成成分のオイラー角を取得
			r::math::Vector3D	EulerXYZ ( void ) const;
			r::math::Vector3D	EulerXZY ( void ) const;
			r::math::Vector3D	EulerYXZ ( void ) const;
			r::math::Vector3D	EulerYZX ( void ) const;
			r::math::Vector3D	EulerZXY ( void ) const;
			r::math::Vector3D	EulerZYX ( void ) const;
			//! XYZ軸に対してオイラー角3つを指定して回転行列を作成する
			/*! いずれは展開したいです*/
			const Matrix33& rotateXYZ ( const r::math::Vector3D& rot );
			const Matrix33& rotateXZY ( const r::math::Vector3D& rot );
			const Matrix33& rotateYXZ ( const r::math::Vector3D& rot );
			const Matrix33& rotateYZX ( const r::math::Vector3D& rot );
			const Matrix33& rotateZXY ( const r::math::Vector3D& rot );
			const Matrix33& rotateZYX ( const r::math::Vector3D& rot );
		public:
			// メンバ変数
			union {
				struct {
					r_f32		_11;
					r_f32		_12;
					r_f32		_13;
					r_f32		_21;
					r_f32		_22;
					r_f32		_23;
					r_f32		_31;
					r_f32		_32;
					r_f32		_33;
				};
				r_f32			m[3][3];
				r_f32			f[9];
			};
		};
	}
}
#include "../rtti/r_rtti_reflection_typename.h"
namespace r{
	namespace rtti{
		//! r::math::Matrix33
		template<>
		static inline
		const r_cstr	getTypeNameStr<r::math::Matrix33>() {
			return _RST ( "r::math::Matrix33" );
		}
	}
}

#endif // _R_MATH_MATRIX33_H_
